There are two types of SCSI drivers: device level drivers and host adapter drivers. The host adapter drivers handle the low-level communication over the SCSI interface, such as programming the SCSI interface chip or board, negotiating synchronous or wide mode, and handling disconnect/reconnect. The device drivers handle high-level communication, primarily by issuing SCSI commands and interpreting sense data.
Some examples of host adapter drivers are wd93, wd95, and jag. Examples of device level drivers are dksc, tpsc, and smfd.
There are four basic interfaces used to communicate to a host adapter driver: scsi_info, scsi_alloc, scsi_free, and scsi_command(). Each of these interfaces is implemented as an array of pointers to functions, indexed by a host adapter driver number. The host adapter driver number is determined from the adapter number. The adapter number ranges are defined in sys/scsi.h, and are different on different architectures. In general, Integral SCSI controllers start at adapter 0, and Interphase VME-SCSI (Jaguar) controllers start after the last Integral adapter. Each SCSI bus is considered to be one adapter.
On a POWER Series or Crimson system, for example, Interphase VME-SCSI controller 3, bus 0, would be adapter number 10. On a CHALLENGE/Onyx system, VME-SCSI controller 3, bus 0, would be adapter number 134. See the definitions of SCSI_SGISTART, SCSI_SGICOUNT, SCSI_JAGSTART, and SCSI_JAGCOUNT in sys/scsi.h.
SCSI_XXXSTART definitions define the starting adapter number for the various adapter types. SCSI_XXXCOUNT is the number of possible adapters for a given controller type. Both SCSIDRIVER_WD93 and SCSIDRIVER_WD95 are part of Silicon Graphics-built SCSI controllers, and so use the SCSI_SGISTART and SCSI_SGICOUNT #define's.
For example, on a CHALLENGE system, the second bus on Interphase VME-SCSI controller 4 would be considered adapter number 137. Counting SCSI_JAGSTART as 128, (controller 4 * 2 adapters per controller) + bus 1 (the second bus on the controller) gives 9 to be added to the value of SCSI_JAGSTART to give adapter (or bus) number 137 from the point of view of a SCSI device driver.
Typically, the major and minor numbers of a device are used to determine the adapter number, which can then be used to index into scsi_driver_table.
adap = sdk_adap_num(device);
driver_num = scsi_driver_table[adap];
Synopsis
struct scsi_target_info * (*scsi_info[]) (u_char adapter, u_char target, u_char lun);Arguments
The following would be the way to use scsi_info to get information about target 5, LUN 0 on Interphase controller 4, bus 1 (the second bus):
info = (*scsi_info[SCSIDRIVER_JAG])(9, 5, 0);
Synopsis
Argumentsint (*scsi_alloc[driver_num]) (unsigned char adap, unsigned char target, unsigned char lun, int option, void (*callback)());
SCSIALLOC_EXCLUSIVE specifies that the device driver wants to have exclusive access to the target in question. If any other device has allocated a connection, the scsi_alloc call fails.
SCSIALLOC_QDEPTH, the queue depth that your driver requests, is the bottom eight bits of option. It is considered advice only, and may or may not be followed.
If the call to scsi_alloc is successful, the type of SCSI adapter being used (SCSIDRIVER_WD93, SCSIDRIVER_WD95, or SCSIDRIVER_JAG) is returned. Otherwise, this routine returns 0, which indicates that no connection could be established between the host adapter driver and your driver, probably because the arguments were included for the adapter.
Not all scsi_request type structure members are of interest to your device driver (some members are of interest only to the SCSI host adapter driver and may change across releases of the operating system). Following is the definition of the structure scsi_request:
struct scsi_request { /* values filled in by device driver */ u_char sr_ctlr; u_char sr_target; u_char sr_lun; u_char sr_tag; /* first byte of tag message */ u_char *sr_command; /* scsi command */ ushort sr_cmdlen; /* length of scsi command */ ushort sr_flags; /* direction of data transfer */ ulong sr_timeout; /* in seconds */ u_char *sr_buffer; /* location of data */ uint sr_buflen; /* amount of data to transfer */
u_char *sr_sense; /* where to put sense data in /*case of CC */ ulong sr_senselen;/* size of buffer allocated for /*sense data */ void (*sr_notify)(struct scsi_request *); /* callback pointer */ void *sr_bp; /* usually a buf_t pointer */ /* spare pointer used by device driver */ void *sr_dev; /* spare fields used by host adapter driver */ void *sr_ha; /* usually used for linked list /*of req's */ void *sr_spare; /* used as spare pointer, int, /*etc. */ /* results filled in by host adapter driver */ uint sr_status; /* Status of command */ u_char sr_scsi_status; /* SCSI status byte */ u_char sr_ha_flags; /* flags used by host /*adapter driver */ short sr_sensegotten; /* number of sense bytes /* received; -1 == err */ uint sr_resid; /* amount of sr_buflen not /*transferred */ }; typedef struct scsi_request scsi_request_t;Before calling scsi_command[](), your driver must fill in the values indicated above. Some are optional.
SC_CLASS0_SZ is a command size of 6 bytes.
SC_CLASS1_SZ is a command size of 10 bytes.
SC_CLASS2_SZ is a command size of 12 bytes.
SRF_DIR_IN -- Data associated with the command will be written into memory.
SRF_FLUSH -- A cache operation is required on the data.
SRF_MAP -- The sr_buffer address needs to be mapped -- it is a kernel virtual address.
SRF_MAPBP -- sr_bp has a pointer to a struct buf that is not mapped (BP_ISMAPPED returns false).
SRF_AEN_ACK -- This request acknowledges an error in a previous request. Once a scsi_request is returned with an error, all further requests are returned with SC_ATTN, without being acted upon, until SRF_AEN_ACK is set.
SRF_NEG_ASYNC -- This request attempts to negotiate async xfer mode on this command (if currently using sync xfers).
SRF_NEG_SYNC -- This request attempts to negotiate sync xfer mode on this command if currently asynchronous. It may be ignored by some adapter drivers, either always or if the driver has previously failed to negotiate sync xfer mode with this target. This overrides the SCSIALLOC_NOSYNC flag to scsi_alloc (if it has been specified).
SC_GOOD -- indicates no error. The bus successfully processed the SCSI command; however, the command itself may still have failed (see sr_scsi_status).
SC_TIMEOUT -- indicates selection timeout. The device did not respond to selection within 250 milliseconds.
SC_HARDERR -- indicates hardware or SCSI device error, usually a SCSI bus reset, possibly caused by a bad phase or time-out on some other device.
SC_PARITY -- indicates an unrecoverable parity error on the SCSI bus.
SC_MEMERR -- indicates an unrecoverable parity or ECC error from host memory.
SC_CMDTIME -- indicates the command did not complete before the time-out specified in s_timeoutval elapsed.
SC_ALIGN -- indicates the buffer address did not meet the alignment requirements of the system. Most Silicon Graphics systems require starting buffer addresses to be on a four-byte boundary.
SC_ATTN -- indicates the scsi_request() has been aborted by a SCSI bus reset, the device, or the driver, due to an error in another request.
SC_REQUEST -- indicates the request is not a valid request. This can be because no scsi_alloc has been done successfully or because the scsi_request() has conflicting or illegal values, such as sr_notify being set to NULL.
ST_GOOD -- indicates the target has successfully completed the SCSI command. On this value, sr_sensegotten must be checked to see if a check condition occurred on the command.
ST_CHECK -- indicates that the request sense command generated by the host adapter driver in response to a check condition also got a check condition. This is a special case. If a device reports a "check condition" status, the host adapter driver automatically issues a request sense command and reports the status of that command in this byte. If sr_sense is set and sr_senselen is > 0, sr_sensegotten is set to the number of bytes of sense data received, or to -1 if an error occurs during the request sense command.
ST_COND_MET -- indicates search condition satisfied.
ST_BUSY -- indicates the target is busy. Normally, the driver should delay, then reissue the command.
ST_INT_GOOD -- indicates this status is reported for every command in a series of linked commands. Although they are not supported, these linked commands may sometimes work.
ST_RES_CONF -- indicates an attempt to access a logical unit or an extent within a logical unit that reserves that type of access to another SCSI device.
This byte corresponds to the SCSI command status byte as documented in the SCSI specifications.
Synopsis
The arguments to scsi_free are similar to those to scsi_alloc except that no option argument is used.int (*scsi_free[driver_num]) (unsigned char adap, unsigned char target, unsigned char lun, void (*callback)());